package ac.github.oa.internal.core.ui

import ac.github.oa.OriginAttribute
import ac.github.oa.api.common.Matcher
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.InventoryCloseEvent
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.InventoryHolder
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.ItemMeta
import taboolib.common.platform.event.SubscribeEvent
import taboolib.common5.Coerce
import taboolib.library.configuration.ConfigurationSection
import taboolib.library.xseries.XMaterial
import taboolib.library.xseries.getItemStack
import taboolib.module.nms.getName
import taboolib.module.ui.buildMenu
import taboolib.module.ui.type.Basic
import taboolib.platform.compat.depositBalance
import taboolib.platform.compat.withdrawBalance
import taboolib.platform.util.buildItem
import taboolib.platform.util.isAir
import taboolib.platform.util.modifyMeta
import taboolib.platform.util.sendLang

class Sell(val player: Player) : InventoryHolder {

    val items = mutableMapOf<Int, Data>()

    var power: Double = -1.0

    private val inventory = Bukkit.createInventory(this, 3 * 9, config.getString("title")!!)

    companion object {
        val config: ConfigurationSection
            get() = OriginAttribute.config.getConfigurationSection("options.sell")!!

        val itemP: String
            get() = config.getString("\$item")!!

        val submitItem0: ItemStack
            get() = config.getItemStack("icon-submit0")!!

        val submitItem1: ItemStack
            get() = config.getItemStack("icon-submit1")!!

        val noneKeywords: List<String>
            get() = config.getStringList("none")

        val keywords: List<String>
            get() = config.getStringList("keywords")

        val default: Double
            get() = config.getDouble("default", 1.0)

        val ITEMS = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)

        val FLAP = listOf(18, 19, 20, 21, 23, 24, 25, 26)

        val SUBMIT = 22

        @SubscribeEvent
        fun e(e: InventoryCloseEvent) {
            val inventory = e.inventory
            val holder = inventory.holder as? Sell ?: return
            val player = e.player
            ITEMS.forEach {
                val itemStack = inventory.getItem(it) ?: return@forEach
                if (itemStack.isAir()) return@forEach
                player.inventory.addItem(itemStack)
                inventory.setItem(it, null)
            }
        }

        @SubscribeEvent
        fun e(e: InventoryClickEvent) {
            val inventory = e.inventory
            val holder = inventory.holder as? Sell ?: return
            val player = e.whoClicked as Player

            if (holder.power != -1.0) {
                e.isCancelled = true
            }

            if (e.rawSlot in FLAP) {
                e.isCancelled = true
                return
            }

            if (e.rawSlot == SUBMIT) {
                e.isCancelled = true
                if (holder.power == -1.0) {
                    holder.power = 0.0
                    ITEMS.forEach {
                        val itemStack = inventory.getItem(it) ?: return@forEach
                        if (itemStack.isAir()) return@forEach
                        if (!isSell(itemStack)) return@forEach
                        holder.items[it] = Data(itemStack).also {
                            holder.power += it.power
                        }
                    }
                    if (holder.items.isEmpty()) {
                        holder.power = -1.0
                        return
                    }
                    inventory.setItem(SUBMIT, submitItem1.modifyMeta<ItemMeta> {
                        setDisplayName(displayName.replace("{count}", holder.power.toString()))
                        lore = lore?.flatMap {
                            if (it.contains("\$item")) {
                                holder.toList(it)
                            } else {
                                listOf(it.replace("{count}", holder.power.toString()))
                            }
                        }
                    })
                } else {
                    holder.items.forEach { inventory.setItem(it.key, null) }
                    player.depositBalance(holder.power)
                    player.sendLang("item-sell-successful", holder.power)
                    holder.power = -1.0
                    holder.items.clear()
                    inventory.setItem(SUBMIT, submitItem0)
                }
            }


        }

        fun getPower(itemStack: ItemStack): Double {
            val list = itemStack.itemMeta?.lore ?: emptyList()
            val string = list.firstOrNull { s1 -> keywords.any { it in s1 } } ?: return default * itemStack.amount
            return Matcher.single(string).amount * itemStack.amount
        }

        fun isSell(itemStack: ItemStack): Boolean {
            val list = itemStack.itemMeta?.lore ?: emptyList()
            return list.any { s1 -> noneKeywords.any { it !in s1 } }
        }
    }

    // 18 19 20 21 22 23 24 25 26
    fun build() {
        FLAP.forEach { inventory.setItem(it, config.getItemStack("icon-#")) }
        inventory.setItem(SUBMIT, submitItem0)
        player.openInventory(inventory)
    }

    class Data(val itemStack: ItemStack) {

        val name = itemStack.getName()

        val amount = itemStack.amount

        val power = getPower(itemStack)

    }

    fun toList(string: String): List<String> {
        return items.values.map {
            string.replace(
                "\$item",
                itemP.replace("{0}", it.name).replace("{1}", it.amount.toString()).replace("{2}", it.power.toString())
            )
        }
    }

    override fun getInventory(): Inventory {
        return inventory
    }

}